﻿#include "VAOneXMLAdaptorSeaShell.h"
#include "rapidxml.hpp"
#include <QFile>
#include <iostream>
#include <QDebug>
#include "FITKAcousticsModel/FITKAbstractSEASubSys.h"
#include "FITKAcousticsModel/FITKSEASubSysShellPlate.h"
#include "FITKAcousticsModel/FITKSEASubSysShellCurved.h"
#include "FITKAcousticsPhysics/FITKAcousticsPhysics.h"
#include "FITKAcousticsPhysics/FITKAcousticsSpectraManager.h"
#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"
#include "FITKAcousticsPhysics/FITKAcousticsAbsPhysicsProp.h"
#include "FITKAcousticsModel/FITKAcousticsDiscModel.h"
#include "FITKAcousticsModel/FITKAcousticsSEAModel.h"
#include "FITKAcousticsModel/FITKAbstractSEAFace.h"

namespace IO
{
    bool VAOneXMLAdaptorSeaShell::adaptR()
    {
        bool b = true;

        //指针检查
        if(nullptr == _node)
        {
            return false;
        }

        Acoustics::FITKAcousticsSEASubSysManager *dataManager = dynamic_cast<Acoustics::FITKAcousticsSEASubSysManager*>(_dataObj);
        if (nullptr == dataManager)
        {
            return false;
        }

        if (Acoustics::FITKAbstractSEASubSys::SEASSNone == getNodeType())
        {
            //key信息未适配的按照自己独立处理返回成功
            return true;
        }

        rapidxml::xml_node<char>* node = _node->first_node("Shell");

        while (nullptr != node)
        {
            rapidxml::xml_node<char>* child =  node->first_node(getNodeName().toStdString().c_str());
            if (nullptr != child)// 判断节点是否存在  类型不一致时存在为空的逻辑
            {
                Acoustics::FITKAbstractSEASubSysShell *data = createDataObjNode();

                if (nullptr != data)
                {
                    readSingleShell(child, data);

                    dataManager->appendDataObj(data);
                }
            }

            node = node->next_sibling("Shell");
        }

        // 返回操作是否成功
        return b;
    }

    bool VAOneXMLAdaptorSeaShell::adaptW()
    {
        Acoustics::FITKAcousticsSEASubSysManager *dataManager = dynamic_cast<Acoustics::FITKAcousticsSEASubSysManager*>(_dataObj);

        if ((nullptr == dataManager) || (nullptr == _node)) return false;

        bool b = true;

        //key信息未适配的按照自己独立处理返回成功
        if (Acoustics::FITKAbstractSEASubSys::SEASSNone == getNodeType()) return true;

        // 获取列表
        QList<Acoustics::FITKAbstractSEASubSys*> list = dataManager->getSubSysByType(getNodeType());

        // 循环处理shell
        for (auto data : list)
        {
            // 创建shell节点
            rapidxml::xml_node<char>* node = createNodeElement(_node, "Shell");
            if (nullptr == node)  continue;

            //创建具体子节点element
            rapidxml::xml_node<char>* child = createNodeElement(node, getNodeName());
            if (nullptr == child) continue;

            //单个节点信息写入
            writeSingleShell((Acoustics::FITKAbstractSEASubSysShell *)data, child);
        }

        // 返回操作是否成功
        return b;
    }

    void VAOneXMLAdaptorSeaShell::readPhyProperty(rapidxml::xml_node<char>* node, Acoustics::FITKAbstractSEASubSysShell *data)
    {
        if ((nullptr == node) || (nullptr == data)) return;

        bool bOK = true;

        QString str = readStrAttribute(node, "crosssection", &bOK);
        if (true != bOK)
        {
            qDebug() << "read crosssection failed";
            return;
        }

        int id = getPhyPropertyId(str);
        data->setPropSection(id);
    }

    void VAOneXMLAdaptorSeaShell::readDamping(rapidxml::xml_node<char>* node, Acoustics::FITKAbstractSEASubSysShell *data)
    {
        if ((nullptr == node) || (nullptr == data)) return;

        //structural_damping="true"
        //damping_flexure="1% loss factor"
        //damping_extension="1% loss factor"
        //damping_shear="1% loss factor"

        bool bOK = true;
        QString str = readStrAttribute(node, "structural_damping", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read structural_damping failed";
            return;
        }

        data->setFromUserSpectraState(strToBool(str));

        QString flexure = readStrAttribute(node, "damping_flexure", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read structural_damping failed";
            return;
        }

        QString extension = readStrAttribute(node, "damping_extension", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read damping_extension failed";
            return;
        }

        QString shear = readStrAttribute(node, "damping_shear", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read damping_shear failed";
            return;
        }

        //获取physis管理器
        Acoustics::FITKAcousticsPhysics* phyMgr = FITKAPP->getGlobalData()->getPhysicsData<Acoustics::FITKAcousticsPhysics>();
        if (nullptr == phyMgr) return;

        //获取频谱管理器
        Acoustics::FITKAcousticsSpectraManager* spectraMgr = phyMgr->getFITKAcousticsSpectraManager();
        if (nullptr == spectraMgr) return;

        //将字符串信息转换成ojectid
        QList<Acoustics::FITKAcousticsAbstractSpectra*> spectraList = spectraMgr->getSpectraByType(Acoustics::FITKAcousticsAbstractSpectra::AcousticsSpectraType::Damping);
        for (auto key : spectraList)
        {
            QString name = key->getDataObjectName();
            if (flexure == name) data->setFlexureSpectraID(key->getDataObjectID());
            if (extension == name) data->setExtensionSpectraID(key->getDataObjectID());
            if (shear == name) data->setShearSpectraID(key->getDataObjectID());
        }
    }

    void VAOneXMLAdaptorSeaShell::readRadiation(rapidxml::xml_node<char>* node, Acoustics::FITKAbstractSEASubSysShell *data)
    {
        if ((nullptr == node) || (nullptr == data)) return;

        bool bOK = true;

        rapidxml::xml_node<char> *child = node->first_node("RadiationOptions");
        if (nullptr == child)
        {
            qDebug()<<"read RadiationOptions error";
            return;
        }

        //radiation
        //radiating_area_factor="1" radiating_perimeter_factor="1"
        double value = readDoubleAttribute(child, "radiating_area_factor", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read radiating_area_factor failed";
            return;
        }
        data->setEffRadiationAreaMagnification(value);

        value = readDoubleAttribute(child, "radiating_perimeter_factor", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read radiating_perimeter_factor failed";
            return;
        }
        data->setEffRadiationPerimeterMagnification(value);
    }

    void VAOneXMLAdaptorSeaShell::readFlexureWave(rapidxml::xml_node<char> *node, Acoustics::FITKAbstractSEASubSysShell *data)
    {
        if ((nullptr == node) || (nullptr == data)) return;

        //获取弯曲波的数据
        //flexure
        //include_in_matrix_solution_flexure="true"
        //ud_modal_density_flexure="modal density, 1 mode/(rad/s)"
        //override_L_factor="2" override_W_factor="2" override_ModalLW_flag="true"

        bool bOK = true;
        QString str = readStrAttribute(node, "override_ModalLW_flag", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read override_ModalLW_flag failed";
            return;
        }

        data->setFlexureCorrectionSDP(strToBool(str));

        double value = readDoubleAttribute(node, "override_L_factor", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read override_L_factor error";
            return;
        }
        data->setFlexureSDPLengthMagnification(value);

        value = readDoubleAttribute(node, "override_W_factor", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read override_W_factor error";
            return;
        }
        data->setFlexureSDPWidthMagnification(value);

        rapidxml::xml_node<char> *child = node->first_node("PlateWavefieldUD");
        if (nullptr == child)
        {
            qDebug()<<"read PlateWavefieldUD error";
            return;
        }

        str = readStrAttribute(child, "include_in_matrix_solution_flexure", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read include_in_matrix_solution_flexure error";
            return;
        }
        data->setFlexureInSEAMatrixSolution(strToBool(str));

        //不做判断 字段可能不存在
        str = readStrAttribute(child, "ud_modal_density_flexure", &bOK);
        data->setFlexureModelDensityState(false);
        int id = getModalDensityId(str);
        if (-1 != id)
        {
            data->setFlexureModelDensityID(id);
            data->setFlexureModelDensityState(true);
        }
    }

    void VAOneXMLAdaptorSeaShell::readExtensionWave(rapidxml::xml_node<char> *node, Acoustics::FITKAbstractSEASubSysShell *data)
    {
        if ((nullptr == node) || (nullptr == data)) return;

        //include_in_matrix_solution_extension="true"
        //include_in_matrix_solution_shear="true"
        //ud_modal_density_extension="modal density, 1 mode/Hz"
        //ud_modal_density_shear="modal density, 1 mode/Hz"

        rapidxml::xml_node<char> *child = node->first_node("PlateWavefieldUD");
        if (nullptr == child)
        {
            qDebug()<<"get PlateWavefieldUD node failed";
            return;
        }

        bool bOK = true;
        QString str = readStrAttribute(child, "include_in_matrix_solution_extension", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read include_in_matrix_solution_extension error";
            return;
        }
        data->setExtensionInSEAMatrixSolution(strToBool(str));

        //字段不一定存在 不做成功判断
        str = readStrAttribute(child, "ud_modal_density_extension", &bOK);
        data->setExtensionModelDensityState(false);

        //转换名字到objectid
        if (true != str.isEmpty())
        {
            int id = getModalDensityId(str);
            if (-1 != id)
            {
                data->setExtensionModelDensityID(id);
                data->setExtensionModelDensityState(true);
            }
        }
    }

    void VAOneXMLAdaptorSeaShell::readShearWave(rapidxml::xml_node<char> *node, Acoustics::FITKAbstractSEASubSysShell *data)
    {
        if ((nullptr == node) || (nullptr == data)) return;

        //include_in_matrix_solution_extension="true"
        //include_in_matrix_solution_shear="true"
        //ud_modal_density_extension="modal density, 1 mode/Hz"
        //ud_modal_density_shear="modal density, 1 mode/Hz"

        rapidxml::xml_node<char> *child = node->first_node("PlateWavefieldUD");
        if (nullptr == child)
        {
            qDebug()<<"get PlateWavefieldUD node failed";
            return;
        }

        bool bOK = true;
        QString str = readStrAttribute(child, "include_in_matrix_solution_shear", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read ud_modal_density_shear error";
            return;
        }
        data->setShearInSEAMatrixSolution(strToBool(str));

        //字段不一定存在 不做成功判断
        str = readStrAttribute(child, "ud_modal_density_shear", &bOK);
        data->setShearModelDensityState(false);

        //转换名字到objectid
        if (true != str.isEmpty())
        {
            int id = getModalDensityId(str);
            if (-1 != id)
            {
                data->setShearModelDensityID(id);
                data->setShearModelDensityState(true);
            }
        }
    }

    void VAOneXMLAdaptorSeaShell::readSingleShell(rapidxml::xml_node<char> *node, Acoustics::FITKAbstractSEASubSysShell *data)
    {
        if ((nullptr == node) || (nullptr == data)) return;
        bool bOK = true;

        //<Name>PID 159</Name>
        rapidxml::xml_node<char> * child = node->first_node("Name");
        if (nullptr != child)
        {
            QString name = readStrNodeValue(child, &bOK);
            if (true != bOK)
            {
                qDebug()<<"read shell name error";
                return;
            }

            data->setDataObjectName(name);//名称可以为空，但是节点不能为空
        }

        //face_id="135"
        int id = readIntAttribute(node, "face_id", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read plate face id failed";
            return;
        }
        id = getFaceObjId(id);
        data->setFaceID(id);

        //crosssection="Uniform shell"
        readPhyProperty(node, data);

        readDamping(node, data);

        //物理属性和噪声控制属性开关
        //property_damping="true" nct_damping="true"
        QString str = readStrAttribute(node, "property_damping", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read property_damping failed";
            return;
        }
        data->setFromPhysicalPropState(strToBool(str));

        str = readStrAttribute(node, "nct_damping", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read nct_damping failed";
            return;
        }
        data->setFromNoiseControlState(strToBool(str));

        //辐射数据
        readRadiation(node, data);

        //波数据
        readFlexureWave(node, data);

        //in-plate  model desity
        //include_in_matrix_solution_extension="true"
        //include_in_matrix_solution_shear="true"
        //ud_modal_density_extension="modal density, 1 mode/Hz"
        //ud_modal_density_shear="modal density, 1 mode/Hz"

        //获取拉伸波的数据
        readExtensionWave(node, data);

        //获取剪切波的数据
        readShearWave(node, data);
    }

    void VAOneXMLAdaptorSeaShell::writePhyProperty(Acoustics::FITKAbstractSEASubSysShell *data, rapidxml::xml_node<char> *node)
    {
        if ((nullptr == node) || (nullptr == data)) return;

        QString name = getPhyPropertyName(data->getPropSectionID());

        writeAttribute(node, "crosssection", name);
        writeAttribute(node, "crosssection_angle", 0);
    }

    void VAOneXMLAdaptorSeaShell::writeDamping(Acoustics::FITKAbstractSEASubSysShell *data, rapidxml::xml_node<char> *node)
    {
        if ((nullptr == node) || (nullptr == data)) return;

        //获取physis管理器
        Acoustics::FITKAcousticsPhysics* phyMgr = FITKAPP->getGlobalData()->getPhysicsData<Acoustics::FITKAcousticsPhysics>();
        if (nullptr == phyMgr) return;

        //获取频谱管理器
        Acoustics::FITKAcousticsSpectraManager* spectraMgr = phyMgr->getFITKAcousticsSpectraManager();
        if (nullptr == spectraMgr) return;

        QString flexure = "",extension = "",shear = "";

        //将ojectid信息转换成字符串
        QList<Acoustics::FITKAcousticsAbstractSpectra*> spectraList = spectraMgr->getSpectraByType(Acoustics::FITKAcousticsAbstractSpectra::AcousticsSpectraType::Damping);
        for (auto key : spectraList)
        {
            QString name = key->getDataObjectName();
            int id = key->getDataObjectID();
            if (data->getFlexureSpectraID() == id) flexure = name;
            if (data->getExtensionSpectraID() == id) extension = name;
            if (data->getShearSpectraID() == id) shear = name;
        }

        writeAttribute(node, "tension_1", 0);
        writeAttribute(node, "tension_2", 0);
        writeAttribute(node, "tension_angle", 0);

        writeAttribute(node, "damping_flexure", flexure);
        writeAttribute(node, "damping_extension", extension);
        writeAttribute(node, "damping_shear", shear);

        writeAttribute(node, "modal_flexure", "false");
        writeAttribute(node, "modal_extension", "false");
        writeAttribute(node, "modal_shear", "false");
        writeAttribute(node, "energy_partition", 0);
        writeAttribute(node, "structural_damping", boolToStr(data->getFromUserSpectraState()));

        //物理属性和噪声控制属性开关
        writeAttribute(node, "property_damping", boolToStr(data->getFromPhysicalPropState()));
        writeAttribute(node, "nct_damping", boolToStr(data->getFromNoiseControlState()));

        //override_L_factor="2" override_W_factor="2" override_ModalLW_flag="true"
        writeAttribute(node, "override_L_factor", data->getFlexureSDPLengthMagnification());
        writeAttribute(node, "override_W_factor", data->getFlexureSDPWidthMagnification());
        writeAttribute(node, "override_ModalLW_flag", boolToStr(data->getFlexureCorrectionSDP()));
        writeAttribute(node, "face_name", "");
        if (data->getSEASubSysType() == Acoustics::FITKAbstractSEASubSys::SEADoublyCurvedShell)
        {
            writeAttribute(node, "projection_type", 0);
        }
        if (data->getSEASubSysType() == Acoustics::FITKAbstractSEASubSys::SEADoublyCurvedShell || data->getSEASubSysType() == Acoustics::FITKAbstractSEASubSys::SEASinglyCurvedShell)
        {
            writeAttribute(node, "override_radii", "true");
            writeAttribute(node, "curvature_1", 0.5);
        }
        
        if (data->getSEASubSysType() == Acoustics::FITKAbstractSEASubSys::SEADoublyCurvedShell)
        {
            writeAttribute(node, "curvature_2", 0.5);
            writeAttribute(node, "curvature_angle", "-0");
        }
    }

    void VAOneXMLAdaptorSeaShell::writeRadiation(Acoustics::FITKAbstractSEASubSysShell *data, rapidxml::xml_node<char> *node)
    {
        if ((nullptr == node) || (nullptr == data)) return;

        rapidxml::xml_node<char>* child = createNodeElement(node, "RadiationOptions");
        if (nullptr == child)
        {
            qDebug()<<"create radiation node failed";
            return;
        }

        //radiation
        writeAttribute(child, "radiating_area_factor", data->getEffRadiationAreaMagnification());
        writeAttribute(child, "radiating_perimeter_factor", data->getEffRadiationPerimeterMagnification());

        writeAttribute(child, "edge_correction", "true");
        writeAttribute(child, "ribs_radiation", "false");
        writeAttribute(child, "ribs_scattering", "false");

        // Baffling
        rapidxml::xml_node<char>* bafflingChild = createNodeElement(child, "Baffling");
        if (nullptr == bafflingChild) return;
        writeAttribute(bafflingChild, "apply_correction", "false");
        writeAttribute(bafflingChild, "correction_db", 0);

        // BoundaryCondition
        rapidxml::xml_node<char>* boundaryConditionChild = createNodeElement(child, "BoundaryCondition");
        if (nullptr == boundaryConditionChild) return;
        writeAttribute(boundaryConditionChild, "apply_correction", "false");
        writeAttribute(boundaryConditionChild, "correction_db", 0);
    }

    void VAOneXMLAdaptorSeaShell::writeWave(Acoustics::FITKAbstractSEASubSysShell *data, rapidxml::xml_node<char> *node)
    {
        if ((nullptr == node) || (nullptr == data)) return;

        rapidxml::xml_node<char> *child = createNodeElement(node, "PlateWavefieldUD");
        if (nullptr == child)
        {
            qDebug()<<"create PlateWavefieldUD node failed";
            return;
        }
        //弯曲波的数据
        //flexure
        //include_in_matrix_solution_flexure="true"
        //ud_modal_density_flexure="modal density, 1 mode/(rad/s)"

        /*if (true == data->getFlexureModelDensityState()) writeAttribute(child, "ud_modal_density_flexure", getModalDensityName(data->getFlexureModelDensityID()));
        if (true == data->getExtensionModelDensityState()) writeAttribute(child, "ud_modal_density_extension", getModalDensityName(data->getExtensionModelDensityID()));
        if (true == data->getShearModelDensityState()) writeAttribute(child, "ud_modal_density_shear", getModalDensityName(data->getShearModelDensityID()));*/

        writeAttribute(child, "xsea_alias_flexure", getModalDensityName(data->getFlexureModelDensityID()));
        writeAttribute(child, "xsea_alias_extension", getModalDensityName(data->getExtensionModelDensityID()));
        writeAttribute(child, "xsea_alias_shear", getModalDensityName(data->getShearModelDensityID()));

        writeAttribute(child, "udmodal_in_loads_flexure", boolToStr(data->getFlexureModelDensityState()));
        writeAttribute(child, "udmodal_in_loads_extension", boolToStr(data->getExtensionModelDensityState()));
        writeAttribute(child, "udmodal_in_loads_shear", boolToStr(data->getShearModelDensityState()));

        writeAttribute(child, "modal_mass_for_eu", "false");

        writeAttribute(child, "include_in_matrix_solution_flexure", boolToStr(data->getFlexureInSEAMatrixSolution()));
        writeAttribute(child, "include_in_matrix_solution_extension", boolToStr(data->getExtensionInSEAMatrixSolution()));
        writeAttribute(child, "include_in_matrix_solution_shear", boolToStr(data->getShearInSEAMatrixSolution()));
    }

    void VAOneXMLAdaptorSeaShell::writeSingleShell(Acoustics::FITKAbstractSEASubSysShell *data, rapidxml::xml_node<char> *node)
    {
        if ((nullptr == node) || (nullptr == data)) return;

        //crosssection="Uniform shell"
        writePhyProperty(data, node);

        //face_id="135"
        writeAttribute(node, "face_id", data->getFaceID());

        writeDamping(data, node);

        //<Name>PID 159</Name>
        rapidxml::xml_node<char> * nameChild = createNodeElement(node, "Name", data->getDataObjectName());
        if (nullptr == nameChild) return;

        // Note
        rapidxml::xml_node<char> * noteChild = createNodeElement(node, "Note", "");
        if (nullptr == noteChild) return;

        // PlatePositiveFace
        rapidxml::xml_node<char> * platePositiveFaceChild = createNodeElement(node, "PlatePositiveFace", "");
        if (nullptr == platePositiveFaceChild) return;
        writeAttribute(platePositiveFaceChild, "pressure", 0);

        // PlateNegativeFace
        rapidxml::xml_node<char> * plateNegativeFaceChild = createNodeElement(node, "PlateNegativeFace", "");
        if (nullptr == plateNegativeFaceChild) return;
        writeAttribute(plateNegativeFaceChild, "pressure", 0);

        //波的数据
        writeWave(data, node);

        //辐射数据
        writeRadiation(data, node);
    }
}
